//? name=ShowMethods, shortcut=Ctrl+R, help=List Methods in current file
/**
 * Created by WinKaR on 16/1/11.
 */

import jeb.api.IScript;
import jeb.api.JebInstance;
import jeb.api.ast.Method;
import jeb.api.ui.*;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;

import java.util.List;


public class ShowMethods implements IScript{
    private JebInstance instance;
    private JebUI ui;
    private static final String TAG = "WinKaR";
    private Shell jebMainShell;
    private Display jebDisplay;



    @Override
    public void run(JebInstance jebInstance) {
        this.instance = jebInstance;
        this.ui = instance.getUI();
        this.jebDisplay = Display.getDefault();
        if (!this.instance.isFileLoaded()) {
            e("File not loaded!");
            return;
        }


        Display.getDefault().asyncExec(new Runnable() {
            @Override
            public void run() {
                jebMainShell = jebDisplay.getShells()[0];
                JavaView javaView = ((JavaView) ui.getView(View.Type.JAVA));
                String signature = javaView.getCodePosition().getSignature();
                i("Signature: " + signature);
                String clsName = getClassSignature(signature);
                i("Class Name: "+ clsName);
                for (Object method:
                        instance.getDecompiledClassTree(clsName).getMethods()) {
                    i("Method name: " + ((Method) method).getName());
                }
                MethodsDialog md = new MethodsDialog(jebMainShell, instance.getDecompiledClassTree(clsName).getMethods());
                md.open();
            }
        });

    }


    private class MethodsDialog extends Dialog {
        private final List methods;
        private String response;
        public MethodsDialog(Shell s, List methods) {
            super(s);
            response=null;
            this.methods = methods;
        }

        public String open() {
            final Shell parent = this.getParent();
            final Shell shell = new Shell(parent, SWT.TITLE | SWT.BORDER | SWT.APPLICATION_MODAL);
            shell.setText("Methods");
            shell.setLayout(new GridLayout(1, true));


            Table newTable = new Table(shell, SWT.VIRTUAL | SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION);
            newTable.setLinesVisible(true);
            newTable.setHeaderVisible(true);
            GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
            newTable.setLayoutData(gridData);
            newTable.addSelectionListener(new SelectionAdapter() {
                @Override
                public void widgetSelected(SelectionEvent selectionEvent) {
                    TableItem tableItem = ((TableItem) selectionEvent.item);
                    String signature = tableItem.getText(ColumnName.SIGNATURE.ordinal());
                    i("Method to jump: "+ signature);
                    CodePosition position = new CodePosition(signature);
                    AssemblyView assemblyView = ((AssemblyView) ui.getView(View.Type.ASSEMBLY));
                    assemblyView.setCodePosition(position);
                    ui.focusView(View.Type.ASSEMBLY);
                    instance.decompileMethod(signature);
                    pressKeyTab();
                    shell.dispose();
                    super.widgetSelected(selectionEvent);
                }
            });

            for(ColumnName column: ColumnName.values()) {
                TableColumn newColumn = new TableColumn(newTable, SWT.NONE);
                newColumn.setText(column.name());
            }

            for (Object o: methods) {
                Method method = ((Method) o);

                TableItem newTableItem = new TableItem(newTable, SWT.NONE);
                newTableItem.setText(ColumnName.SIGNATURE.ordinal(), method.getSignature());
                newTableItem.setText(ColumnName.NAME.ordinal(), method.getName());
            }

            for(ColumnName cn : ColumnName.values()) {
                newTable.getColumn(cn.ordinal()).pack();
            }



            Button buttonCancel = new Button(shell, SWT.PUSH);
            buttonCancel.setText("CANCEL");


            buttonCancel.addListener(SWT.Selection, new Listener() {
                public void handleEvent(Event arg0) {
                    shell.dispose();
                    response = null;
                }});


            shell.pack();
            shell.open();

            Display display = parent.getDisplay();
            while(!shell.isDisposed()) {
                if(!display.readAndDispatch()) {
                    display.sleep();
                }
            }

            return response;
        }
    }

    private void pressKeyTab() {
        Event event = new Event();
        event.type = SWT.KeyDown;
        event.keyCode = SWT.TAB;
        this.jebDisplay.post(event);
    }

    private String getClassSignature(String signature) {
        return signature.split(";")[0].split("\\$")[0] + ";";
    }

    private  enum ColumnName {NAME, SIGNATURE}


    private enum LogPriority {ERROR, WARN, INFO, DEBUG}

    private void log(LogPriority priority, String message) {
        if(priority != null) {
            instance.print(String.format("[%s] [%s]\t%s", TAG, priority.name(), message));
        } else {
            instance.print(String.format("[%s]\t%s", TAG, message));
        }
    }

    private void d(String msg) { log(LogPriority.DEBUG, msg); }
    private void i(String msg) { log(LogPriority.INFO, msg); }
    private void w(String msg) { log(LogPriority.WARN, msg); }
    private void e(String msg) { log(LogPriority.ERROR, msg); }
}
